using System;
using System.Data;
using System.Xml;
using SharpObjects.Configuration;
using System.Collections;
using SharpObjects.Configuration.ConfigurationProviders;
using SharpObjects.Instantiation;
using SharpObjects.Interfaces;

namespace SharpObjects.Data
{
	public class DbParameterDescriptor : IDbParameterDescriptor
	{
		protected ParameterDirection m_direction;
		protected eDataType m_type;
		protected object m_value;
		protected bool m_bNullable;
		protected DataRowVersion m_rowversion;
		protected string m_sName;
		protected string m_sSourceColumn; 
		protected int m_nSize;
		protected byte m_nPrecision;
		protected byte m_nScale;
        protected bool m_bDirectSql = false;

		public DbParameterDescriptor(
			string sName, 
			eDataType type, 
			ParameterDirection direction,
			int nSize,
			object objValue,
			string sSourceColumn,
			DataRowVersion RowVersion,
			bool bNullable,
			byte nPrecision,
			byte nScale)
		{
			m_sName = sName;
			m_type = type;
			m_direction = direction;
			m_nSize = nSize;
			m_value = objValue;
			m_sSourceColumn = sSourceColumn;
			m_rowversion = RowVersion;
			m_bNullable = bNullable;
			m_nPrecision = nPrecision;
			m_nScale = nScale;
		}
			

		public DbParameterDescriptor(
			string sName, 
			string sType, 
			ParameterDirection direction,
			int nSize,
			object objValue,
			string sSourceColumn,
			DataRowVersion RowVersion,
			bool bNullable,
			byte nPrecision,
			byte nScale
			)
		{
			m_sName = sName;

            if (string.IsNullOrEmpty(sType))
            {
                m_type = eDataType.None;
            }
            else
            {
                m_type = (eDataType)Enum.Parse(typeof(eDataType), sType, true);
            } 
            
            m_direction = direction;
			m_nSize = nSize;
			m_value = objValue;
			m_sSourceColumn = sSourceColumn;
			m_rowversion = RowVersion;
			m_bNullable = bNullable;
			m_nPrecision = nPrecision;
			m_nScale = nScale;
		}

		public DbParameterDescriptor(
			string sName, 
			eDataType type, 
			ParameterDirection direction,
			int nSize,
			object objValue,
			string sSourceColumn,
			DataRowVersion RowVersion,
			bool bNullable,
			byte nPrecision
			)
		{
			m_sName = sName;
			m_type = type;
			m_direction = direction;
			m_nSize = nSize;
			m_value = objValue;
			m_sSourceColumn = sSourceColumn;
			m_rowversion = RowVersion;
			m_bNullable = bNullable;
			m_nPrecision = nPrecision;
			m_nScale = 0;
		}

		public DbParameterDescriptor(
			string sName, 
			string sType, 
			ParameterDirection direction,
			int nSize,
			object objValue,
			string sSourceColumn,
			DataRowVersion RowVersion,
			bool bNullable,
			byte nPrecision
			)
		{
		    m_sName = sName;

            if(string.IsNullOrEmpty(sType))
            {
                m_type = eDataType.None;
            }
            else
            {
                m_type = (eDataType)Enum.Parse(typeof(eDataType), sType, true);
            }
            
            m_direction = direction;
			m_nSize = nSize;
			m_value = objValue;
			m_sSourceColumn = sSourceColumn;
			m_rowversion = RowVersion;
			m_bNullable = bNullable;
			m_nPrecision = nPrecision;
			m_nScale = 0;
		}

		public DbParameterDescriptor(
			string sName, 
			eDataType type, 
			ParameterDirection direction,
			int nSize,
			object objValue,
			string sSourceColumn,
			DataRowVersion RowVersion,
			bool bNullable
			)
		{
			m_sName = sName;
			m_type = type;
			m_direction = direction;
			m_nSize = nSize;
			m_value = objValue;
			m_sSourceColumn = sSourceColumn;
			m_rowversion = RowVersion;
			m_bNullable = bNullable;
			m_nPrecision = 0;
			m_nScale = 0;
		}

		public DbParameterDescriptor(
			string sName, 
			string sType, 
			ParameterDirection direction,
			int nSize,
			object objValue,
			string sSourceColumn,
			DataRowVersion RowVersion,
			bool bNullable
			)
		{
			m_sName = sName;

            if (string.IsNullOrEmpty(sType))
            {
                m_type = eDataType.None;
            }
            else
            {
                m_type = (eDataType)Enum.Parse(typeof(eDataType), sType, true);
            } 
            
            m_direction = direction;
			m_nSize = nSize;
			m_value = objValue;
			m_sSourceColumn = sSourceColumn;
			m_rowversion = RowVersion;
			m_bNullable = bNullable;
			m_nPrecision = 0;
			m_nScale = 0;
		}

		public DbParameterDescriptor(
			string sName, 
			string sType, 
			ParameterDirection direction,
			int nSize,
			object objValue,
			string sSourceColumn,
			DataRowVersion RowVersion
			)
		{
			m_sName = sName;

            if (string.IsNullOrEmpty(sType))
            {
                m_type = eDataType.None;
            }
            else
            {
                m_type = (eDataType)Enum.Parse(typeof(eDataType), sType, true);
            } 
            
            m_direction = direction;
			m_nSize = nSize;
			m_value = objValue;
			m_sSourceColumn = sSourceColumn;
			m_rowversion = RowVersion;
			m_bNullable = true;
			m_nPrecision = 0;
			m_nScale = 0;
		}

		public DbParameterDescriptor(
			string sName, 
			eDataType type, 
			ParameterDirection direction,
			int nSize,
			object objValue,
			string sSourceColumn,
			DataRowVersion RowVersion
			)
		{
			m_sName = sName;
			m_type = type;
			m_direction = direction;
			m_nSize = nSize;
			m_value = objValue;
			m_sSourceColumn = sSourceColumn;
			m_rowversion = RowVersion;
			m_bNullable = true;
			m_nPrecision = 0;
			m_nScale = 0;
		}

		public DbParameterDescriptor(
			string sName, 
			string sType, 
			ParameterDirection direction,
			int nSize,
			object objValue,
			string sSourceColumn
			)
		{
			m_sName = sName;
            
            if (string.IsNullOrEmpty(sType))
            {
                m_type = eDataType.None;
            }
            else
            {
                m_type = (eDataType)Enum.Parse(typeof(eDataType), sType, true);
            } 
            
            m_direction = direction;
			m_nSize = nSize;
			m_value = objValue;
			m_sSourceColumn = sSourceColumn;
			m_rowversion = DataRowVersion.Current;
			m_bNullable = true;
			m_nPrecision = 0;
			m_nScale = 0;
		}

		public DbParameterDescriptor(
			string sName, 
			eDataType type, 
			ParameterDirection direction,
			int nSize,
			object objValue,
			string sSourceColumn
			)
		{
			m_sName = sName;
			m_type = type;
			m_direction = direction;
			m_nSize = nSize;
			m_value = objValue;
			m_sSourceColumn = sSourceColumn;
			m_rowversion = DataRowVersion.Current;
			m_bNullable = true;
			m_nPrecision = 0;
			m_nScale = 0;
		}

		public DbParameterDescriptor(
			string sName, 
			string sType, 
			ParameterDirection direction,
			int nSize,
			object objValue
			)
		{
			m_sName = sName;

            if(string.IsNullOrEmpty(sType))
            {
                m_type = eDataType.None;
            }
            else
            {
                m_type = (eDataType)Enum.Parse(typeof(eDataType), sType, true);
            }

			m_direction = direction;
			m_nSize = nSize;
			m_value = objValue;
			m_sSourceColumn = sName;
			m_rowversion = DataRowVersion.Current;
			m_bNullable = true;
			m_nPrecision = 0;
			m_nScale = 0;
		}

		public DbParameterDescriptor(
			string sName, 
			eDataType type, 
			ParameterDirection direction,
			int nSize,
			object objValue
			)
		{
			m_sName = sName;
			m_type = type;
			m_direction = direction;
			m_nSize = nSize;
			m_value = objValue;
			m_sSourceColumn = sName;
			m_rowversion = DataRowVersion.Current;
			m_bNullable = true;
			m_nPrecision = 0;
			m_nScale = 0;
		}

        public DbParameterDescriptor(string sName, string sDirectSqlExpression)
        {
            m_sName = sName;
            m_nSize = 0;
            m_value = sDirectSqlExpression;
            m_sSourceColumn = null;
            m_rowversion = DataRowVersion.Current;
            m_bNullable = false;
            m_nPrecision = 0;
            m_nScale = 0;
            m_bDirectSql = true;
        }
        
        public DbParameterDescriptor()
		{
			m_sName = null;
			m_nSize = 0;
			m_value = null;
			m_sSourceColumn = null;
			m_rowversion = DataRowVersion.Current;
			m_bNullable = false;
			m_nPrecision = 0;
			m_nScale = 0;
		}

/*
	<param_descriptors>
		<param_descriptor name=":PROCESS_ID" type="Int" direction="Input" />
		<param_descriptor name=":DESCRIPTION" type="UnicodeString" direction="Input" nullable="true" precision="0" scale="0" size="200" source_column=":DESCRIPTION" row_version="Current"/>
	</param_descriptors>
*/
		public DbParameterDescriptor(XmlElement desc_elem)
		{
			XmlConfigurationProvider par = new XmlConfigurationProvider(desc_elem);

			string sRequestedType = par.GetString("@type");

			this.EDataType = (eDataType)Enum.Parse(typeof(eDataType), sRequestedType, true);

			this.ParameterName = par.GetString("@name");
			this.Direction = MapPSharpObjectsirection(par.GetString("@direction"));	
			this.IsNullable = par.GetBoolean("@nullable", false);
			this.Precision = (byte)par.GetInteger("@precision", 0);
			this.Scale = (byte)par.GetInteger("@scale", 0);
			this.Size = par.GetInteger("@size", 0);
			this.SourceColumn = par.GetString("@source_column", this.ParameterName);
			this.SourceVersion = MapRowVersion(par.GetString("@row_version", "Current"));
		}

		protected System.Data.ParameterDirection MapPSharpObjectsirection(string sDirection)
		{
			ParameterDirection d = (ParameterDirection)Enum.Parse(typeof(System.Data.ParameterDirection), sDirection, true);
			return d;
		}

		protected System.Data.DataRowVersion MapRowVersion(string sRowVersion)
		{
			DataRowVersion rv = (DataRowVersion)Enum.Parse(typeof(DataRowVersion), sRowVersion, true);
			return rv;
		}





		//#region IDataParameter Members

		public ParameterDirection Direction { get { return m_direction; } set { m_direction = value; } }
		public eDataType EDataType { get { return m_type; } set { m_type = value; } }
		System.Data.DbType System.Data.IDataParameter.DbType { get { return DbType.Object; } set { } }
		public object Value { get { return m_value; } set { m_value = value; } }
		public bool IsNullable { get { return m_bNullable; } set { m_bNullable = value; } }
		public DataRowVersion SourceVersion { get { return m_rowversion; } set { m_rowversion = value; } }
		public string ParameterName { get { return m_sName; } set { m_sName = value; } }
		public string SourceColumn { get { return m_sSourceColumn; } set { m_sSourceColumn = value; } }

		//#endregion

		//#region IDbParameter Members

		public int Size { get { return m_nSize; } set { m_nSize = value; } }
		public byte Precision { get { return m_nPrecision; } set { m_nPrecision = value; } }
		public byte Scale { get { return m_nScale; } set { m_nScale = value; } }
        public bool IsDirectSqlExpression { get { return m_bDirectSql; } set { m_bDirectSql = value; } }

		//#endregion

		public override string ToString()
		{
			return m_sName;
		}

	    public static readonly ITypeDescriptor TypeDescriptor = new TypeDescriptor()
	                                                                {
	                                                                    AssemblyPath = "SharpObjects.Data",
	                                                                    TypeName = typeof(DbParameterDescriptor).FullName,
	                                                                    Type = typeof (DbParameterDescriptor)
	                                                                };

	}
}
